<?php

/**
 * @author Dany Mottier
 * @version 1.0
 */
class StreamReader extends Base {

  /** @var string The name of the file to work with. */
  private $filename;

  /** @var resource The handle of the file when it's open. */
  private $handle;

  /**
   * Open the file specified in parameter.<br />
   *
   * @param string $filename The file to open.
   *
   * @link http://be.php.net/manual/en/function.is-string.php
   * @link http://be.php.net/manual/en/function.fopen.php
   */
  public function __construct($filename) {
    if (is_string($filename)) {
      if (file_exists($filename)) {
        $this->filename = $filename;
      } else {
        throw new IOException("\$filename file does not exists.");
      }
    } else {
      throw new IllegalArgumentException("\$filename parameter must be a string");
    }
  }

  /**
   * Close the handle on object destruction.<br />
   *
   * @link http://be.php.net/manual/en/function.is-null.php
   */
  public function __destruct() {
    if (!is_null($this->handle)) {
      fclose($this->handle);
    }
  }

  /**
   * Define if the pointer is at the end of the file.<br />
   *
   * @return boolean Return TRUE if the pointer is ath the end of the file, FALSE otherwise.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.feof.php
   */
  public function endOfStream() {
    return feof($this->handle);
  }

  /**
   * Close the open handle of the file.<br />
   *
   * @return boolean Return TRUE on succes or FALSE on failure.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.fclose.php
   */
  public function close() {
    $return = fclose($this->handle);

    if ($return) {
      $this->handle = NULL;
    }

    return $return;
  }

  /**
   * Opens file in read only.
   * Binds a named resource, specified by filename, to a stream.
   */
  public function open() {
    $this->handle = fopen($this->filename, "r");
  }

  /**
   * Return the next character at the pointer position without consuming it.<br />
   *
   * @return char Return the next char at the pointer position.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.fgetc.php
   * @link http://be.php.net/manual/en/function.fseek.php
   */
  public function peek() {
    $char = fgetc($this->handle);

    fseek($this->handle, -1, SEEK_CUR);

    return $char;
  }

  /**
   * Read one or more character at the pointer position and consume it.<br />
   *
   * @param int $length [Optional] The number of character to consume.
   *
   * @return string Return the next character at the pointer position.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.is-int.php
   * @link http://be.php.net/manual/en/function.fread.php
   * @link http://be.php.net/manual/en/function.fgetc.php
   */
  public function read($length = 0) {
    if (is_int($length)) {
      if ($length > 0) {
        return fread($this->handle, $length);
      } else {
        return fgetc($this->handle);
      }
    } else {
      throw new IllegalArgumentException("$length parameter must be an integer.");
    }
  }

  /**
   * Read a block from $index with a $length, beginning at the top of the file.
   * @param Integer $index The start index to read the block.
   * @param Integer $length The length of characters to read.
   * @return String Return a part of the string from the file.
   * @link http://be.php.net/manual/en/function.fseek.php
   * @link http://be.php.net/manual/en/function.fread.php
   */
  public function readBlock(Integer $index, Integer $length) {
    $block = String::EMPTY_STRING;

    if (fseek($this->handle, $index->integerValue(), SEEK_SET) == 0) {
      $block = fread($this->handle, $length->integerValue());
    }

    return new String($block);
  }

  /**
   * Read a complete line at the pointer position.<br />
   *
   * @return string Return a complete line at the pointer position.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.fgets.php
   */
  public function readLine() {
    return fgets($this->handle);
  }

  /**
   * Reads the entire file.<br />
   *
   * @param string $filename The path to the file to read.
   *
   * @return string The complete content of the file.<br /><br />
   *
   * @link http://be.php.net/manual/en/function.file-get-contents.php
   */
  public static function readToEnd($filename) {
    return file_get_contents($filename);
  }

  /**
   * Returns the current file name.
   * @return string The current file name.
   */
  public function getFilename() {
    return $this->filename;
  }

}

?>
